package com.ruizhong.centercontroll.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruizhong.centercontroll.dao.TVideoMapper;
import com.ruizhong.centercontroll.entity.TCommand;
import com.ruizhong.centercontroll.entity.TVideo;
import com.ruizhong.centercontroll.service.TCommandService;
import com.ruizhong.centercontroll.service.TVideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.websocket.EncodeException;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TVideoServiceImpl extends ServiceImpl<TVideoMapper, TVideo> implements TVideoService {

    @Autowired
    private TCommandService tCommandService;


    @Override
    @Transactional
    public void saveNewVideoList(List<Map<String, Object>> videoList, Integer pageId, boolean isNew) {
        final HashMap<Integer, List<Map<String, Object>>> videoIdMapInitCommandList = new HashMap<>();
        final HashMap<Integer, List<Map<String, Object>>> videoIdMapClickCommandList = new HashMap<>();
        deleteVideosByPageId(pageId);
        videoList.stream().forEach(videoOB -> {
            TVideo tVideo = new TVideo();
            tVideo.setPageId(pageId);
            tVideo.setW(Double.parseDouble(videoOB.get("w").toString()));
            tVideo.setH(Double.parseDouble(videoOB.get("h").toString()));
            tVideo.setX(videoOB.get("x") == null?0: Double.parseDouble(videoOB.get("x").toString()));
            tVideo.setY(videoOB.get("y") == null?0:Double.parseDouble(videoOB.get("y").toString()));
            tVideo.setZ(Integer.parseInt(videoOB.get("z").toString()));
            Object displayVariableName = videoOB.get("displayVariableName");
            Object displayVariableValue = videoOB.get("displayVariableValue");
            tVideo.setDisplayVariableName(displayVariableName == null ? null : displayVariableName.toString());
            tVideo.setDisplayVariableValue(displayVariableValue == null ? null : displayVariableValue.toString());
            Object conditionShow = videoOB.get("conditionShow");
            tVideo.setConditionShowData(conditionShow == null ? null : (Boolean) conditionShow ? 1 : 0);
            Object streamVariable = videoOB.get("streamVariable");
            tVideo.setStreamVariable(streamVariable == null ? null : streamVariable.toString());
            Object videoType = videoOB.get("videoType");
            tVideo.setVideoType(videoType == null ?null:(Integer) videoType);
            List<Map<String, Object>> clickCommandList = null;
            List<Map<String,Object>> initCommandList = null;
            Map logicGraph = (Map) videoOB.get("logicGraph");
            if (!isNew){
                clickCommandList = (List<Map<String, Object>>) videoOB.get("clickCommandList");
                initCommandList = (List<Map<String, Object>>) videoOB.get("initCommandList");
            }else{
                ObjectMapper mapper = new ObjectMapper();
                try {
                    String logicGraphString = mapper.writeValueAsString(logicGraph);
                    tVideo.setLogicGraphData(logicGraphString);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                Map<String, List> typeMapCommandList = TCommandServiceImpl.getCommandsByGraph(logicGraph);
                initCommandList = typeMapCommandList.get("initCommandList");
                clickCommandList = typeMapCommandList.get("releaseCommandList");
            }
            save(tVideo);
            videoIdMapInitCommandList.put(tVideo.getId(), initCommandList);
            videoIdMapClickCommandList.put(tVideo.getId(),clickCommandList);
        });
        Runnable runnable = new Runnable() {
            public void run() {
                tCommandService.saveCommandList("VIDEO", "init", videoIdMapInitCommandList);
                tCommandService.saveCommandList("VIDEO", "click", videoIdMapClickCommandList);
            }
        };
        new Thread(runnable).start();
    }

    @Override
    public List<TVideo> getVideosByPageId(Integer pageId, Double pageWidth, Double pageHeight, Double aimPageWidth, Double aimPageHeight, Boolean display) throws JsonProcessingException {
        List<TVideo> videos = lambdaQuery()
                .eq(TVideo::getPageId, pageId)
                .list();
        for (TVideo video : videos) {
            if (!display){
                String logicGraphData = video.getLogicGraphData();
                if (!StringUtils.isEmpty(logicGraphData)){
                    ObjectMapper mapper = new ObjectMapper();
                    Map map = mapper.readValue(logicGraphData, Map.class);
                    video.setLogicGraph(map);
                }
                List<TCommand> initCommands = tCommandService.getCommandListByMain(video.getId(), video.getType(), "init");
                initCommands = tCommandService.fillTCommands(initCommands);
                video.setInitCommandList(initCommands);
            }else {
                video.setLogicGraphData(null);
            }

            if (aimPageHeight != -1 && aimPageWidth != -1) {
                video.setW(Math.floor((video.getW() * aimPageWidth) / pageWidth));
                video.setH(Math.floor((video.getH() * aimPageHeight) / pageHeight));
                video.setX(Math.floor((video.getX() * aimPageWidth) / pageWidth));
                video.setY(Math.floor((video.getY() * aimPageHeight) / pageHeight));
            }
            video.setConditionShow(video.getConditionShowData() == null ? false : video.getConditionShowData() == 1);

        }
        return videos;
    }

    @Override
    public List<TVideo> getVideoIdsByPageId(Integer pageId) {
        List<TVideo> list = lambdaQuery()
                .select(TVideo::getId)
                .eq(TVideo::getPageId, pageId)
                .list();
        return list;
    }

    @Override
    public void executeCommand(Map<String, Object> conditionMap, String ip) throws EncodeException, IOException {
        Map<String, Object> variableMap = (Map<String, Object>) conditionMap.get("variableSet");
        String wsToken = conditionMap.get("wsToken").toString();
        TVideo tVideo = getById(Integer.parseInt(conditionMap.get("id").toString()));
        List<TCommand> commandList = tCommandService.getCommandListByMain(tVideo.getId(), tVideo.getType(), "click");
        tCommandService.executeCommandsAndGetReply(commandList, variableMap, wsToken, ip);
    }

    private void deleteVideosByPageId(Integer pageId) {
        QueryWrapper<TVideo> deleteWrapper = new QueryWrapper<>();
        deleteWrapper.lambda().eq(TVideo::getPageId, pageId);
        remove(deleteWrapper);
    }
}
